﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;
using System.Management;
using System.Xml.Linq;
using System.Xml.XPath;
using System.ServiceProcess;
using System.Data.Sql;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;

//Mark Rowe 
//From the IRDev Library Project.
namespace AutoDeploy.Common.Library
{
    public static class ExternalHelper
    {
        public static class Helper
        {
            public static bool registryEntryExistsInLocalMachine(string key)
            {
                Microsoft.Win32.RegistryKey localMachine = Microsoft.Win32.Registry.LocalMachine;
                try
                {
                    Microsoft.Win32.RegistryKey keyToSearch = localMachine.OpenSubKey(key);
                    foreach (string s in keyToSearch.GetSubKeyNames().ToList())
                    {
                        //has some subkey name therefore that registry entry is there.
                        return true;
                    }
                }
                catch (Exception ex)
                {
                    return false;
                }
                return false;
            }

            public static bool isInstalled(string searchFor, bool isExact)
            {
                if (isExact)
                {
                    return StringHelper.ListValueMatch(searchFor, ReturnListOfInstalledPrograms(), false);
                }
                return StringHelper.ListValueContains(searchFor, ReturnListOfInstalledPrograms(), false);
            }

            public static bool isServiceInstalled(string searchFor, bool isExact)
            {
                if (isExact)
                {
                    return StringHelper.ListValueMatch(searchFor, ReturnListOfInstalledServices(), false);
                }
                return StringHelper.ListValueContains(searchFor, ReturnListOfInstalledServices(), false);
            }

            public static List<string> ReturnListOfInstalledPrograms()
            {
                List<string> ls = new List<string>();
                try
                {
                    //There is no Microsoft.Win64 
                    Microsoft.Win32.RegistryKey localMachine = Microsoft.Win32.Registry.LocalMachine;
                    Microsoft.Win32.RegistryKey uninstall = localMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall");
                    foreach (string applicationSubKeyName in uninstall.GetSubKeyNames().ToList())
                    {
                        Microsoft.Win32.RegistryKey currentApp = uninstall.OpenSubKey(applicationSubKeyName);
                        if (currentApp.GetValue("DisplayName") != null)
                        {
                            ls.Add(currentApp.GetValue("DisplayName").ToString());
                        }
                        currentApp.Close();
                    }
                    uninstall.Close();
                    localMachine.Close();
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                ls.Sort();
                return ls;
            }

            public static List<string> ReturnListOfInstalledServices()
            {
                List<string> ls = new List<string>();
                foreach (ServiceController sc in ServiceController.GetServices().ToList())
                {
                    ls.Add(sc.ServiceName);
                }
                return ls;
            }

            public static void RunShellCommand(string commandToRun)
            {
                Process p = System.Diagnostics.Process.Start(commandToRun);
                p.WaitForExit();
            }

            public static void RunShellCommand(string commandToRun, string user, string password)
            {
                string domain = string.Empty;
                if (user.Contains("\\"))
                {
                    domain = user.Substring(0, user.IndexOf("\\")).Replace("\\", "");
                    user = user.Substring(user.IndexOf("\\")).Replace("\\", "");
                }
                if (user.Contains("@"))
                {
                    domain = user.Substring(user.IndexOf("@")).Replace("@", "");
                    user = user.Substring(0, user.IndexOf("@")).Replace("@", "");
                }
                System.Security.SecureString pass = new System.Security.SecureString();
                foreach(char c in password)
                {
                    pass.AppendChar(c);
                }
                Process p = System.Diagnostics.Process.Start(commandToRun, user, pass, domain);
                p.WaitForExit();
            }


            public static string CheckForFileLocation(string s, ref List<string> Errors)
            {
                bool isQuoted = s.Contains("\"[Program Files]");
                string pre = string.Empty;
                string post = string.Empty;
                string file = string.Empty;
                string temp = string.Empty;
                int Preindex = s.IndexOf("[Program Files]");
                if (Preindex > -1)
                {
                    if (isQuoted)
                    {
                        pre = (Preindex > 0 ? s.Substring(0, Preindex) : "");
                        temp = (pre.Length != 0 ? s.Replace(pre, "") : s);
                        file = temp.Substring(0, temp.LastIndexOf("\""));
                        post = temp.Replace(file, "");
                    }
                    else
                    {
                        pre = (Preindex > 0 ? s.Substring(0, Preindex) : "");
                        temp =(pre.Length != 0 ? s.Replace(pre, ""): s);
                        file = temp;
                        post = temp.Replace(file, "");
                    }
                    if (isFileInLocation(ref file))
                    {
                        s = pre + file + post;
                    }
                    else
                    {
                        s = pre + file + post;
                        Errors.Add("Could Not Find File :" + s);
                    }
                }
                    return s;
            }

            public static bool isFileInLocation(ref string uri)
            {
                List<string> ls = new List<string>();
                if (Environment.Is64BitOperatingSystem)
                {
                    ls.Add(uri.Replace("[Program Files]", Environment.GetEnvironmentVariable("ProgramFiles(x86)")));
                    ls.Add(uri.Replace("[Program Files]", Environment.GetEnvironmentVariable("ProgramFiles")));
                }
                else
                {
                    ls.Add(uri.Replace("[Program Files]", Environment.GetEnvironmentVariable("ProgramFiles"))); 
                }
                foreach (string s in ls)
                {
                    if (File.Exists(s))
                    {
                        uri = s.Trim();
                        return true;
                    }
                }
                return false;
            }

            //Covered with command line just prepare app with powershell locations.
            //public static void RunPowerShellCommand(string command)
            //{
            //    RunShellCommand("Powershell " + command);
            //}

            //public static void RunPowerShellCommand(string command, string user, string password, string domain)
            //{
            //    RunShellCommand("Powershell " + command, "", user, password, domain);
            //}
            
            //Write this for managed Code. 
            //public static void RunPowerShellScripts(string script, List<string> parameters)
            //{ 
            //}
            //public static void RunPowerShellScripts(string script, List<string> parameters, string user, string domain, string passWord)
            //{
            //    using (new Automation.Impersonator(user, domain, password))
            //    {
            //        using (RunspaceInvoke invoker = new RunspaceInvoke())
            //        {
            //            invoker.Invoke("Set-ExecutionPolicy Unrestricted");
            //        }
            //    } 
            //}

            //Neat new System.Xml.Xpath stuff ;)

            public static void ExecuteNonQuery(string statementToRun, string connString)
            {
                SqlConnection sqlConn = new SqlConnection(connString);
                SqlCommand sqlCommand = new SqlCommand(statementToRun, sqlConn);
                SqlDataAdapter sqlDataAdapter = new SqlDataAdapter();
                try
                {
                    sqlConn.Open();
                    sqlDataAdapter.SelectCommand = sqlCommand;
                    sqlDataAdapter.SelectCommand.ExecuteNonQuery();
                }
                catch (System.Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    sqlConn.Close();
                }
                sqlConn.Close();
            }

            public static void RunSqlScript(string uri, string connString)
            {
                ExecuteNonQuery(ReadAFile(uri), connString);
            }

            public static void RunSqlCommand(string command, string connString)
            {
                ExecuteNonQuery(command, connString);
            }

            public static string ReadAFile(string uri)
            {
                if (File.Exists(uri))
                {
                    return File.ReadAllText(uri);
                }
                return string.Empty;
            }

            public static void WriteAFile(string myWrite, string fileToWrite, bool appendToFile)
            {
                try
                {
                    using (StreamWriter sw = new StreamWriter(fileToWrite, appendToFile))
                    {
                        sw.WriteLine(myWrite);
                    }
                }
                catch (Exception ex)
                {

                }
            }

            public static void WriteAFile(List<string> myWrite, string fileToWrite, bool appendToFile)
            {
                using (StreamWriter sw = new StreamWriter(fileToWrite, appendToFile))
                {
                    foreach (string s in myWrite)
                    {
                        sw.WriteLine(s);
                    }
                }
            }
        }
    }
}